﻿#pragma once

#include <xy/geom/nurbs.h>
#include <xy/math/ndarray.h>

namespace xy
{

namespace geom
{

template <std::size_t D, std::size_t N> class manifold
{
    static_assert(D > 0, "D must be greater than 0");
    static_assert(N > 0, "N must be greater than 0");
    using vecd_t = vec<D, double>; // 参数域向量
    using vec_t = vec<N, double>;  // 空间向量

  public:
    /**
     * @brief 计算曲线上点的位置
     *
     * @param[in] param
     * @return vec_t
     */
    virtual vec_t d0(const vecd_t &param) const = 0;

    /**
     * @brief 计算曲线上点的位置和导数
     *
     * @param[in] param
     * @return std::array<vec_t, 1 + D>
     */
    virtual std::array<vec_t, 1 + D> d1(const vecd_t &param) const = 0;

    /**
     * @brief 计算曲线上点的位置、导数和二阶导数
     *
     * @param[in] param
     * @return std::array<vec_t, 1 + D + D *(D + 1) / 2>
     */
    virtual std::array<vec_t, 1 + D + D *(D + 1) / 2> d2(const vecd_t &param) const = 0;

    /**
     * @brief 获得 i 维度的参数范围
     *
     * @param[in] i
     * @return std::array<double, 2>
     */
    virtual std::array<double, 2> bound(std::size_t i = 0) const = 0;
};

template <std::size_t N> using curve = manifold<1, N>;
template <std::size_t N> using surface = manifold<2, N>;

} // namespace geom

} // namespace xy